/*
 * Copyright (c) 2018.
 * http://www.ulabcare.com
 */

package com.mt.roll.core.api;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.mt.roll.core.base.IErrorCode;
import com.mt.roll.core.exception.ApiException;

import java.util.Collection;
import java.util.Map;

/**
 * 接口参数断言工具类
 *
 * @author jiff
 * @date 2018/11/1
 * @since 1.0
 */
public class Assert {

    protected Assert() {
        // to do noting
    }

    /**
     * 断言参数等于0，否则抛出错误消息
     *
     * @param num       断言参数
     * @param errorCode 错误消息
     */
    public static void eqZero(Integer num, IErrorCode errorCode) {
        if (num == null || num != 0) {
            Assert.fail(errorCode);
        }
    }

    /**
     * 断言参数等于0，否则抛出错误消息
     *
     * @param num     断言参数
     * @param message 错误消息
     */
    public static void eqZero(Integer num, String message) {
        if (num == null || num != 0) {
            Assert.fail(message);
        }
    }

    /**
     * 断言参数小于0，否则抛出错误消息
     *
     * @param num       断言参数
     * @param errorCode 错误消息
     */
    public static void ltZero(Integer num, IErrorCode errorCode) {
        if (num == null || num >= 0) {
            Assert.fail(errorCode);
        }
    }

    /**
     * 断言参数小于0，否则抛出错误消息
     *
     * @param num     断言参数
     * @param message 错误消息
     */
    public static void ltZero(Integer num, String message) {
        if (num == null || num >= 0) {
            Assert.fail(message);
        }
    }

    /**
     * 断言小于等于0，否则抛出错误消息
     *
     * @param num       断言参数
     * @param errorCode 错误消息
     */
    public static void leZero(Integer num, IErrorCode errorCode) {
        if (num == null || num > 0) {
            Assert.fail(errorCode);
        }
    }

    /**
     * 断言小于等于0，否则抛出错误消息
     *
     * @param num     断言参数
     * @param message 错误消息
     */
    public static void leZero(Integer num, String message) {
        if (num == null || num > 0) {
            Assert.fail(message);
        }
    }

    /**
     * 断言参数大于0，否则抛出错误消息
     *
     * @param num       断言参数
     * @param errorCode 错误消息
     */
    public static void gtZero(Integer num, IErrorCode errorCode) {
        if (num == null || num <= 0) {
            Assert.fail(errorCode);
        }
    }

    /**
     * 断言参数大于0，否则抛出错误消息
     *
     * @param num     断言参数
     * @param message 错误消息
     */
    public static void gtZero(Integer num, String message) {
        if (num == null || num <= 0) {
            Assert.fail(message);
        }
    }

    /**
     * 断言大于等于0，否则抛出错误消息
     *
     * @param num       断言参数
     * @param errorCode 错误消息
     */
    public static void geZero(Integer num, IErrorCode errorCode) {
        if (num == null || num < 0) {
            Assert.fail(errorCode);
        }
    }

    /**
     * 断言大于等于0，否则抛出错误消息
     *
     * @param num     断言参数
     * @param message 错误消息
     */
    public static void geZero(Integer num, String message) {
        if (num == null || num < 0) {
            Assert.fail(message);
        }
    }

    /**
     * 断言num1大于num2，否则抛出错误消息
     *
     * @param num1      断言参数1
     * @param num2      断言参数2
     * @param errorCode 错误消息
     */
    public static void gt(Integer num1, Integer num2, IErrorCode errorCode) {
        if (num1 <= num2) {
            Assert.fail(errorCode);
        }
    }

    /**
     * 断言num1大于num2，否则抛出错误消息
     *
     * @param num1    断言参数1
     * @param num2    断言参数2
     * @param message 错误消息
     */
    public static void gt(Integer num1, Integer num2, String message) {
        if (num1 <= num2) {
            Assert.fail(message);
        }
    }

    /**
     * 断言num1大于等于num2，否则抛出错误消息
     *
     * @param num1      断言参数1
     * @param num2      断言参数2
     * @param errorCode 错误消息
     */
    public static void ge(Integer num1, Integer num2, IErrorCode errorCode) {
        if (num1 < num2) {
            Assert.fail(errorCode);
        }
    }

    /**
     * 断言num1大于等于num2，否则抛出错误消息
     *
     * @param num1    断言参数1
     * @param num2    断言参数2
     * @param message 错误消息
     */
    public static void ge(Integer num1, Integer num2, String message) {
        if (num1 < num2) {
            Assert.fail(message);
        }
    }

    /**
     * 断言obj1 eq obj2，否则抛出错误消息
     *
     * @param obj1      断言参数1
     * @param obj2      断言参数2
     * @param errorCode 错误消息
     */
    public static void eq(Object obj1, Object obj2, IErrorCode errorCode) {
        if (!obj1.equals(obj2)) {
            Assert.fail(errorCode);
        }
    }

    /**
     * 断言obj1 eq obj2，否则抛出错误消息（错误码统一为{@link IErrorCode#CODE_FAILED}）
     *
     * @param obj1    断言参数1
     * @param obj2    断言参数2
     * @param message 错误消息
     */
    public static void eq(Object obj1, Object obj2, String message) {
        if (!obj1.equals(obj2)) {
            Assert.fail(message);
        }
    }

    /**
     * 断言参数为true，否则抛出错误消息
     *
     * @param condition 断言参数
     * @param errorCode 错误消息
     */
    public static void isTrue(boolean condition, IErrorCode errorCode) {
        if (!condition) {
            Assert.fail(errorCode);
        }
    }

    /**
     * 断言参数为false，否则抛出错误消息
     *
     * @param condition 断言参数
     * @param errorCode 错误消息
     */
    public static void isFalse(boolean condition, IErrorCode errorCode) {
        if (condition) {
            Assert.fail(errorCode);
        }
    }

    /**
     * 断言给定的参数都为null，否则抛出错误消息
     *
     * @param errorCode  错误消息
     * @param conditions 断言参数
     */
    public static void isNull(IErrorCode errorCode, Object... conditions) {
        if (ObjectUtils.isNotNull(conditions)) {
            Assert.fail(errorCode);
        }
    }

    /**
     * 断言给定的参数都不为null，否则抛出错误消息
     *
     * @param errorCode  错误消息
     * @param conditions 断言参数
     */
    public static void notNull(IErrorCode errorCode, Object... conditions) {
        if (ObjectUtils.isNull(conditions)) {
            Assert.fail(errorCode);
        }
    }

    /**
     * 断言给定的参数都为null，否则抛出错误消息（错误码统一为{@link IErrorCode#CODE_FAILED}）
     *
     * @param message    错误消息
     * @param conditions 断言参数
     */
    public static void isNull(String message, Object... conditions) {
        if (ObjectUtils.isNotNull(conditions)) {
            Assert.fail(message);
        }
    }

    /**
     * 断言给定的参数都不为null，否则抛出错误消息（错误码统一为{@link IErrorCode#CODE_FAILED}）
     *
     * @param message    错误消息
     * @param conditions 断言参数
     */
    public static void notNull(String message, Object... conditions) {
        if (ObjectUtils.isNull(conditions)) {
            Assert.fail(message);
        }
    }

    /**
     * <p>
     * 抛出失败消息
     * </p>
     *
     * @param errorCode 异常错误码
     */
    public static void fail(IErrorCode errorCode) {
        throw new ApiException(errorCode);
    }

    /**
     * 根据断言条件判断是否抛出错误消息
     *
     * @param condition 断言条件，true则抛出错误消息，否则正常执行
     * @param errorCode 错误消息
     */
    public static void fail(boolean condition, IErrorCode errorCode) {
        if (condition) {
            Assert.fail(errorCode);
        }
    }

    /**
     * <p>
     * 抛出失败消息
     * </p>
     *
     * @param message 错误消息
     */
    public static void fail(String message) {
        throw new ApiException(message);
    }

    /**
     * 根据断言条件判断是否抛出错误消息
     *
     * @param condition 断言条件，true则抛出错误消息，否则正常执行
     * @param message   错误消息
     */
    public static void fail(boolean condition, String message) {
        if (condition) {
            Assert.fail(message);
        }
    }

    /**
     * 断言参数不为空，否则抛出错误消息
     *
     * @param array     断言参数
     * @param errorCode 错误消息
     */
    public static void notEmpty(Object[] array, IErrorCode errorCode) {
        if (ObjectUtils.isEmpty(array)) {
            Assert.fail(errorCode);
        }
    }

    /**
     * 断言数组中的对象没有null元素，否则抛出错误消息
     *
     * @param array     断言参数
     * @param errorCode 错误消息
     */
    public static void noNullElements(Object[] array, IErrorCode errorCode) {
        if (array != null) {
            for (Object element : array) {
                if (element == null) {
                    Assert.fail(errorCode);
                }
            }
        }
    }

    /**
     * 断言参数不为空，否则抛出错误消息
     *
     * @param collection 断言参数
     * @param errorCode  错误消息
     */
    public static void notEmpty(Collection<?> collection, IErrorCode errorCode) {
        if (CollectionUtils.isNotEmpty(collection)) {
            Assert.fail(errorCode);
        }
    }

    /**
     * 断言参数不为空，否则抛出错误消息
     *
     * @param map       断言参数
     * @param errorCode 错误消息
     */
    public static void notEmpty(Map<?, ?> map, IErrorCode errorCode) {
        if (ObjectUtils.isEmpty(map)) {
            Assert.fail(errorCode);
        }
    }

    /**
     * 断言对象是给定类型的实例，否则抛出错误消息
     *
     * @param type      断言类型
     * @param obj       断言对象
     * @param errorCode 错误消息
     */
    public static void isInstanceOf(Class<?> type, Object obj, IErrorCode errorCode) {
        Assert.notNull(errorCode, type);
        if (!type.isInstance(obj)) {
            Assert.fail(errorCode);
        }
    }

    public static void isAssignable(Class<?> superType, Class<?> subType, IErrorCode errorCode) {
        Assert.notNull(errorCode, superType);
        if (subType == null || !superType.isAssignableFrom(subType)) {
            Assert.fail(errorCode);
        }
    }

}
